<?php

declare(strict_types=1);

namespace app\common;

use think\App;
use think\exception\ValidateException;
use think\Validate;
use app\utils\Redis as RedisDB;
use think\facade\Db;
/**
 * 控制器基础类
 */
abstract class AdminController
{
    /**
     * Request实例
     * @var \think\Request
     */
    protected $adminRoleId = 1; // 管理员角色ID
    protected $adminRole = 'admin'; // 管理员角色ID
    protected $request;
    protected $userId;
    protected $userInfo;
    protected $userToken;

    protected $model;
    protected $uRedis;
    protected $pRedis;
    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

    /**
     * 构造方法
     * @access public
     * @param  App  $app  应用对象
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->uRedis = new RedisDB('user');
        $this->pRedis = new RedisDB('perms');
        $this->request = $this->app->request;
        if (empty($this->userId)) {
            $this->userId = $this->app->request->uid;
            $this->userToken = $this->app->request->token;
        }
        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize()
    {

    }

    /**
     * 获取where条件
     * @param array $datas
     * @param array $rule
     * @return array
     */
    protected function whereSql(array $datas, array $rule)
    {
        $where = [];
        foreach ($datas as $key => $value) {
            if (!empty($value) && $value !== '' && $key !== 'page' && $key !== 'limit') {
                if (isset($rule[$key])) {
                    $option = $rule[$key];
                    $nowKey = isset($option['field']) ? $option['field'] : $key;
                    $nowVal = $option['mode'] == 'like' ? "%$value%" : $value;
                    $where[] = [$nowKey, $option['mode'], $nowVal];
                } else {
                    $where[] = [$key, 'like', "%$value%"];
                }
            }
        }
        return $where;
    }

    /**
     * 获取列表
     * @param array $rule
     * @param array $field
     * @return array|string|true
     */
    public function list(array $rule = [], array $field = [], array $association = [], array $hidden = [])
    {
        try {

            $data = input('post.');
            $sort = [];
           if (isset ($data['sort'])) {
              $sort = $data['sort'];
               unset($data['sort']);
           } 
            $where = $this->whereSql($data, $rule);
            $res = [];
            $query = $this->model::where($where)
                ->field($field);
            if(isset($sort['prop'])){
                $sort['prop'] = $this->model->getMappedField($sort['prop']);
                $sort["order"] =  $sort["order"] == "descending" ?  'desc' : 'asc';
                $query->order("$sort[prop] $sort[order]");
            }
            if (count($association) > 0) {
                foreach ($association as $key => $value) {
                    $query->with([
                        $key => function ($q) use ($value) {
                            $q->field($value['field']);
                        }
                    ]);
                }
            }

            if (isset($data['page']) && isset($data['limit'])) {
                $list = $query->paginate([
                    'list_rows' => $data['limit'],
                    'page' => $data['page'],
                ])->hidden($hidden);
                $res = [
                    'rows' => $list->items(),
                    'total' => $list->total(),
                    'hasMore' => $list->hasMore()
                ];
            } else {
                $list = $query->select()->hidden($hidden);
                $res = [
                    'rows' => $list,
                    'total' => count($list)
                ];
            }
            return success('获取成功', $res);
        } catch (\Exception $e) {
            return error($e->getMessage(), 500);
        }
    }

    /**
     * 添加数据
     * @param array $allowField
     * @return array|string|true
     */
    public function add(array $allowField = [], array $association = [], $data = [], $returnId = false)
    {
        try {
            $datas = input('post.');
            if (in_array('create_by', $allowField))
                $datas['create_by'] = $this->userId;
            foreach ($data as $key => $value) {
                $datas[$key] = $value;
            }
            $this->model->startTrans();
            $res = $this->model->allowField($allowField)->create($datas);
            // if (!$res->id) {
            //     throw new \Exception("主表数据保存失败，未生成主键 ID");
            // }
            foreach ($association as $key => $value) {
                if (method_exists($this->model, $key)) {
                    $res->$key()->saveAll($value['save']);
                }
            }
            if ($res) {
                $this->model->commit();
                $return = $returnId ? ['id' => $res->id] : [];
                return success('添加成功', $return);
            } else {
                $this->model->rollback();
                return error('添加失败');
            }
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage(), 500);
        }
    }
    /**
     * 修改数据
     * @param array $allowField
     * @return array|string|true
     */
    public function update(array $allowField = [], array $where = [], array $association = [], array $data = [])
    {
        try {
            $datas = input('post.');
            if (in_array('update_by', $allowField))
                $datas['update_by'] = $this->userId;

            $this->model->startTrans();
            if (count($where) > 0) {
                $query = $this->model->where($where)->find();
            } else {
                $query = $this->model->find($datas['id']);
            }
            foreach ($association as $key => $value) {
                if (method_exists($this->model, $key)) {
                    if (!empty($value['save']))
                        $query->$key()->saveAll($value['save']);
                    if (!empty($value['remove']))
                        $query->$key()->detach($value['remove']);
                }
            }
            foreach ($data as $key => $value) {
                $datas[$key] = $value;
            }
            unset($datas['id']);
            $res = $query->allowField($allowField)->save($datas);
            if ($res) {
                $this->model->commit();
                return success('修改成功', []);
            } else {
                $this->model->rollback();
                return error('修改失败');
            }
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage(), 500);
        }
    }
    public function del($ids, $type = false, $where = [])
    {
        try {
            if (count($where) > 0) {
                $res = $this->model->destroy(function ($q) use ($where) {
                    $q->where($where);
                }, $type);
            } else {
                $ids = explode(',', $ids);
                $res = $this->model->destroy($ids, $type);
            }

            if ($res) {
                return success('删除成功', []);
            } else {
                return error('删除失败');
            }
        } catch (\Exception $e) {
            return error($e->getMessage(), 500);
        }
    }
    /**
     * 获取数据byid
     * @param array $field
     * @param int|string $id
     * @return array|string|true
     */
    public function get($id, array $field = [], array $where = [], array $association = [], array $hidden = [])
    {
        try {
            $query = $this->model->field($field);
            foreach ($association as $key => $value) {
                $query->with([
                    $key => function ($q) use ($value) {
                        $q->field($value['field']);
                    }
                ]);
            }
            if (count($where) > 0) {
                $query->where($where);
                $res = $query->find();
            } else {
                $res = $query->find($id);
            }
            $res = $res->hidden($hidden);
            if ($res) {
                return success('获取成功', $res);
            } else {
                return error('获取失败');
            }
        } catch (\Exception $e) {
            return error($e->getMessage(), 500);
        }
    }
    /**
     * 验证数据
     * @access protected
     * @param  array        $data     数据
     * @param  string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     * @param  bool         $batch    是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, string|array $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                [$validate, $scene] = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }
}
